/**
 * 
 */
package com.thon.security;

import java.io.IOException;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.util.HtmlUtils;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;

/**
 * @author thon
 * @date Mar 21, 2014 10:41:17 AM
 */
public class XssObjectMapper extends ObjectMapper {
	
	public XssObjectMapper() {
		SimpleModule module = new SimpleModule("HTML XSS Serializer",new Version(1, 0, 0, "FINAL", null, null));
        module.addSerializer(new JsonHtmlXssSerializer(String.class));
        module.addDeserializer(String.class, new JsonHtmlXssDeserializer(String.class));
        this.registerModule(module);
    }

	// 输出控制
    class JsonHtmlXssSerializer extends JsonSerializer<String> {

        public JsonHtmlXssSerializer(Class<String> string) {
            super();
        }
        
        public Class<String> handledType() {
            return String.class;
        }

        @Override
        public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            if (value != null) {
                value = value.replaceAll("eval\\((.*)\\)", "");
        		value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']","\"\"");
        		//value = value.replaceAll("script", "...");
                jsonGenerator.writeString(value);
            }
        }
    }
    
    // 输入控制
    class JsonHtmlXssDeserializer extends JsonDeserializer<String> {

        public JsonHtmlXssDeserializer(Class<String> string) {
            super();
        }
        
        public Class<String> handledType() {
            return String.class;
        }

		@Override
		public String deserialize(JsonParser json, DeserializationContext context) throws IOException, JsonProcessingException {
			String value = json.getText();
			value = HtmlUtils.htmlEscape(value.toString());
			value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
			value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
			value = value.replaceAll("'", "&#39;");
			value = value.replaceAll("\"", "&#34;");
    		value = value.replaceAll("eval\\((.*)\\)", "");
    		value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']","\"\"");
    		value = value.replaceAll("script", "...");
    		
    		String[] events = { "onmouseover", "onmouseout", "onmousedown",
		            "onmouseup", "onmousemove", "onclick", "ondblclick",
		            "onkeypress", "onkeydown", "onkeyup", "ondragstart",
		            "onerrorupdate", "onhelp", "onreadystatechange", "onrowenter",
		            "onrowexit", "onselectstart", "onload", "onunload",
		            "onbeforeunload", "onblur", "onerror", "onfocus", "onresize",
		            "onscroll", "oncontextmenu" };
    		for (String event : events) {
    			value = value.replaceAll(event, StringUtils.EMPTY);
			}

			return value;
		}
    }
}
